package com.dhl.fin.api.controller;

import com.dhl.fin.api.common.controller.CommonController;
import com.dhl.fin.api.common.dto.ApiResponse;
import com.dhl.fin.api.common.dto.QueryDto;
import com.dhl.fin.api.common.util.ArrayUtil;
import com.dhl.fin.api.common.util.ObjectUtil;
import com.dhl.fin.api.common.util.WebUtil;
import com.dhl.fin.api.domain.Account;
import com.dhl.fin.api.domain.Project;
import com.dhl.fin.api.domain.Role;
import com.dhl.fin.api.domain.Tree;
import com.dhl.fin.api.service.AccountServiceImpl;
import com.dhl.fin.api.service.ProjectServiceImpl;
import com.dhl.fin.api.service.RoleServiceImpl;
import com.dhl.fin.api.service.TreeServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author CuiJianbo
 * @date 2020.02.25
 */
@Transactional(rollbackFor = Exception.class)
@RestController
@RequestMapping({"account", "projectuser"})
public class AccountController extends CommonController<Account> {

    @Autowired
    private AccountServiceImpl accountService;

    @Autowired
    private TreeServiceImpl treeService;

    @Autowired
    private ProjectServiceImpl projectService;

    @Autowired
    private RoleServiceImpl roleService;


    /**
     * 新增和更新
     *
     * @param domain
     * @return
     * @throws Exception
     */
    @Override
    public ApiResponse saveOrUpdate(Account domain) {
        try {
            if (WebUtil.getRequest().getRequestURI().contains("projectuser")) {
                Long projectId = WebUtil.getLongParam("projectId");
                Long[] roleIds = WebUtil.getLongArrayParam("roleId");
                Long[] userIds = WebUtil.getLongArrayParam("userIds");
                Long[] dataTreeIds = WebUtil.getLongArrayParam("dataTreeIds");

                if (ObjectUtil.notNull(dataTreeIds)) {
                    List<Tree> dataPerTrees = Arrays.stream(dataTreeIds).filter(ObjectUtil::notNull).map(id -> new Tree(id)).collect(Collectors.toList());
                    domain.setDataPerTrees(dataPerTrees);
                } else {
                    List<Tree> trees = new LinkedList<>();
                    domain.setDataPerTrees(trees);
                }

                for (Long userId : userIds) {
                    commonService.deleteMiddleTable("roles", userId);
                    commonService.deleteMiddleTable("projects", userId);
                    commonService.deleteMiddleTable("dataPerTrees", userId);
                    if (ObjectUtil.notNull(roleIds)) {
                        for (Long roleId : roleIds) {
                            commonService.insertMiddleTable("roles", userId, roleId);
                        }
                    }
                    if (ObjectUtil.notNull(dataTreeIds)) {
                        for (Long treeId : dataTreeIds) {
                            commonService.insertMiddleTable("dataPerTrees", userId, treeId);
                        }
                    }

                    commonService.insertMiddleTable("projects", userId, projectId);
                }
                return ApiResponse.success();
            } else {
                Long[] projectIds = WebUtil.getLongArrayParam("projectIds");
                Long userId = WebUtil.getLongParam("id");
                if (ArrayUtil.isNotEmpty(projectIds)) {
                    List<Long> projectIdList = projectService.select(QueryDto.builder()
                            .available()
                            .addWhere(String.format("project.id in (%s)", ArrayUtil.join(projectIds, ",")))
                            .addWhere(String.format("not exists(select id from t_account c where accounts.id = c.id)"))
                            .build()).stream().map(Project::getId).collect(Collectors.toList());

                    for (Long projectId : projectIdList) {
                        projectService.insertMiddleTable("accounts", projectId, userId);
                    }

                    List<Long> roleIds = roleService.select(QueryDto.builder()
                            .available()
                            .addWhere("role.code like '%_sys_manager'")
                            .build()).stream()
                            .map(Role::getId).collect(Collectors.toList());

                    for (Long roleId : roleIds) {
                        commonService.deleteMiddleTable("roles", userId, roleId);
                    }

                    roleIds = roleService.select(QueryDto.builder()
                            .available()
                            .addWhere(String.format("role.project_id in (%s)", ArrayUtil.join(projectIds, ",")))
                            .addWhere("role.code like '%_sys_manager'")
                            .build()).stream()
                            .map(Role::getId).collect(Collectors.toList());
                    for (Long roleId : roleIds) {
                        commonService.insertMiddleTable("roles", userId, roleId);
                    }
                }
                return super.saveOrUpdate(domain);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return ApiResponse.error("保存失败");
    }

    /**
     * 删除
     *
     * @param id
     * @return
     * @throws Exception
     */
    @Override
    public ApiResponse delete(@PathVariable Long id) {
        try {
            if (WebUtil.getRequest().getRequestURI().contains("projectuser")) {
                commonService.deleteMiddleTable("projects", id);
                return ApiResponse.success();
            } else {
                return super.delete(id);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return ApiResponse.error("保存失败");
        }
    }


    /**
     * 更新account状态
     *
     * @param id
     * @return
     * @throws Exception
     */
    @ResponseBody
    @RequestMapping("updatestatus/{id}/{status}")
    public ApiResponse updateAvailable(@PathVariable Long id, @PathVariable String status) {
        try {
            Account account = new Account(id);
            account.setAvailable(Boolean.valueOf(status));
            commonService.updateBySelective(account);
        } catch (Exception e) {
            e.printStackTrace();
            return ApiResponse.error("更新状态失败");
        }
        return ApiResponse.success();
    }

    /**
     * 更新account是否是超级管理员
     *
     * @param id
     * @return
     * @throws Exception
     */
    @ResponseBody
    @RequestMapping("updatesuper/{id}/{status}")
    public ApiResponse updateSuperMG(@PathVariable Long id, @PathVariable String status) {
        try {
            Account account = new Account(id);
            account.setIsSuperManager(Boolean.valueOf(status));
            commonService.updateBySelective(account);
        } catch (Exception e) {
            e.printStackTrace();
            return ApiResponse.error("更新失败");
        }
        return ApiResponse.success();
    }

}
